package com.gaff.emp.core.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import java.text.MessageFormat;
import java.util.List;

@Slf4j
public class ZookeeperUtil {

    public static String createPersistentNode(CuratorFramework client, String nodePath, byte[] nodeValue) throws Exception {
        return client.create().creatingParentsIfNeeded()
                .forPath(nodePath, nodeValue);
    }

    public static String createSequentialPersistentNode(CuratorFramework client, String nodePath, byte[] nodeValue) throws Exception {
        return client.create().creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT_SEQUENTIAL)
                .forPath(nodePath, nodeValue);
    }

    public static String createEphemeralNode(CuratorFramework client, String nodePath, byte[] nodeValue) throws Exception {
        return client.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .forPath(nodePath, nodeValue);
    }

    public static String createSequentialEphemeralNode(CuratorFramework client, String nodePath, byte[] nodeValue) throws Exception {
        return client.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                .forPath(nodePath, nodeValue);
    }

    public static boolean checkExists(CuratorFramework client, String nodePath) {
        try {
            Stat stat = client.checkExists().forPath(nodePath);
            return stat != null;
        } catch (Exception e) {
            log.error(MessageFormat.format("检查Zookeeper节点是否存在出现异常,nodePath:{0}", nodePath), e);
        }
        return false;
    }

    public static List<String> getChildren(CuratorFramework client, String nodePath) throws Exception {
        return client.getChildren().forPath(nodePath);
    }

    public static byte[] getData(CuratorFramework client, String nodePath) throws Exception {
        return client.getData().forPath(nodePath);
    }

    public static void setData(CuratorFramework client, String nodePath, byte[] nodeValue) throws Exception {
        client.setData().forPath(nodePath, nodeValue);
    }

    public static void delete(CuratorFramework client, String nodePath) throws Exception {
        client.delete().guaranteed().forPath(nodePath);
    }

    public static void deleteChildrenIfNeeded(CuratorFramework client, String nodePath) throws Exception {
        client.delete().guaranteed().deletingChildrenIfNeeded().forPath(nodePath);
    }

    public static NodeCache registerNodeCacheListener(CuratorFramework client, String nodePath, NodeCacheListener listener) throws Exception {
        NodeCache nodeCache = new NodeCache(client, nodePath);
        nodeCache.getListenable().addListener(listener);
        nodeCache.start();
        return nodeCache;
    }

    public static PathChildrenCache registerPathChildListener(CuratorFramework client, String nodePath, PathChildrenCacheListener listener) throws Exception {
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, nodePath, true);
        pathChildrenCache.getListenable().addListener(listener);
        pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
        return pathChildrenCache;
    }

    public static TreeCache registerTreeCacheListener(CuratorFramework client, String nodePath, int maxDepth, TreeCacheListener listener) throws Exception {
        TreeCache treeCache = TreeCache.newBuilder(client, nodePath)
                .setCacheData(true)
                .setMaxDepth(maxDepth)
                .build();
        treeCache.getListenable().addListener(listener);
        treeCache.start();
        return treeCache;
    }

}
